昨天做的驗證只針對 Identity 系統,沒有包含到我們的日誌,如果在未登入狀態下於網址列輸入https://localhost:44327/Blog,還是可以看到部落格,讓我們整合驗證。
首先在Blog.razor外層加上<AuthorizeView>,這表示包在其中的內容呈現與否的條件為使用者是否獲得驗證,接著在Blog內容外加上<Authorized>,顧名思義就是通過驗證才能看到內容,另外新增一段未通過驗證的<NotAuthorized>程式碼。這邊要記得加上Context="IdentityContext",否則會跟Blog的<EditForm>本身的context產生衝突。
再去App.razor用<CascadingAuthenticationState>將原本的<Router>包裹,告訴 Blazor 所有 Component 都必須經過驗證。
然後是NavMenu.razor,<Authorized> Component 加上登出連結,登入連結則移到<NotAuthorized>,icon 也改一下。
這時候要重新啟動系統,驗證機制才會生效,可以看到確實擋住了未驗證訪問。
在登入前,先打開 Dev Tool 的 Application 頁籤去看Cookies,目前只有一個 Cookie。
登入後看到新的 Cookie,這就是我們的 Authentication Cookie。
接著來試試看登出,點擊左邊的 Logout,並沒有如想像中登出,而是來到一個 Log out 頁面,右上角還是登入狀態,Authentication Cookie 也還在。
我們去看Logout.cshtml.cs,裡面有OnGet()跟OnPost()分別對應HttpGet及HttpPost,我們從連結點過來的作法是HttpGet,但OnGet()這裡什麼事都沒做,OnPost()則呼叫 ASP.NET Core Identity API 將使用者登出。
Logout.cshtml也找到了一個<form>元素,asp-page這些asp-開頭的程式是 ASP.NET Core 的Tag Helper (標籤協助程式),類似 Angular 的 *ngFor,這邊先略過不提,我們看到這裡用了method="post",還有個<button type="submit">,對應了剛才的OnPost()。
通常不會有使用者按了登出後還要再按一次登出,所以我們這邊改動一下,先給<form>加上id="logoutFormInLogout",再加上一段<script>,這裡用到 IIFE(Immediately Invoked Functions Expressions),意即不需要呼叫就會執行的函式,一旦使用者進入這頁面就會將<form>送出,如此一來,只要點擊NavMenu左邊的 Logout 連結,就可以順利登出了。
如果不想要加上id="logoutFormInLogout"這麼長的 id,也可以用id="logoutForm"就好,根目錄下的 Pages/Shared/_LoginPartial.cshtml裡面有個登出的<form>已經定義了id="logoutForm"這個 id。
不過現在登出後還停留在 Log out頁面似乎沒有意義,所以將OnPost()的else區塊改成return LocalRedirect("~/Blog");,這樣登出後就會回到未驗證的 Blog 頁面。
這樣一來就完成了單一專案的登入驗證機制,而且各種功能、頁面一應俱全,如果只是小型專案的話可以這麼做,明天就來說明這些 ASP.NET Core 的驗證原理。
Ref:立即函式 IIFE
Ref:Blazor cookie authentication Logout page